﻿using System;
using System.Collections.Generic;

namespace IupNET
{
    public class IupBase:IDisposable
    {
        public CallbackHandler CBHandler;

        //a reference to the c iup object
        public IntPtr cobject=IntPtr.Zero;  //TODO: make internal
        string handlename = null;
        private static Int64 unique_id = 1; //used to generate an unique id for evry IUP control
        bool disposed = false;

        //a dictionary with all iup objects created, mapped to c# objects so we can back-map them
        internal static Dictionary<IntPtr, IupBase> allobjects = new Dictionary<IntPtr, IupBase>();


        internal IupBase(IntPtr obj)
        {

            CBHandler = new CallbackHandler(this);

            if (obj != IntPtr.Zero)
                Initialize(obj);
        }


        ~IupBase()
        {
            Dispose(false);
        }

        internal void Initialize(IntPtr obj)
        {
            cobject = obj;
            allobjects[obj] = this;
            HandleName = GenHandleName();
        }

        private string GenHandleName()
        {
            string res = "ID" + unique_id.ToString();
            unique_id++;
            return res;
        }

        public string HandleName
        {
            set
            {
                Iupc.SetHandle(value, cobject);
                handlename = value;
            }
            get
            {
                return handlename;
            }
        }

        

        void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                

                if (allobjects.ContainsKey(cobject))
                    allobjects.Remove(cobject);

                if (cobject != IntPtr.Zero)
                {
                    Iupc.Destroy(cobject);
                    cobject = IntPtr.Zero;
                }

            }
            disposed = true;       
        }


        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        public virtual string GetAttribute(string name)
        {
            return Iupc.GetAttribute(cobject, name);
        }

        public virtual void SetAttribute(string name, string value)
        {
            if (value == null)
                Iupc.SetAttributePtr(cobject, name, IntPtr.Zero);
            else
                Iupc.StoreAttribute(cobject, name, value);
        }

        public virtual void SetAttributePtr(string name, IntPtr value)
        {
          Iupc.SetAttributePtr(cobject, name, IntPtr.Zero);
        }

        public string ClassName
        {
            get { return Iupc.GetClassName(cobject); }
        }

        public string ClassType
        {
            get { return Iupc.GetClassType(cobject); }
        }

        internal static IupBase FindObject(IntPtr obj)
        {
            IupBase res;
            if (allobjects.TryGetValue(obj, out res))
                return res as IupBase;
            return null;
        }

        public static IupBase GetHandle(string name)
        {
            if (name == null)
                return null;
            IntPtr obj = Iupc.GetHandle(name);
            if (obj == IntPtr.Zero)
                return null;
            return FindObject(obj);
        }

        public void Map()
        {
            Iupc.Map(cobject);
        }
        
        public void Unmap()
        {
            Iupc.Unmap(cobject);
        }

    }
}
